package com.djmw.mouse.service.constants;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Constants {
    @JsonAutoDetect
    public static class CommonListType {
        private int id;
        private String name;

        public CommonListType() {
        }
        public CommonListType(int value, String type) {
            this.id = value;
            this.name = type;
        }
        public int getId() {
            return id;
        }
        public String getName() {
            return name;
        }
    }

    public static class CompanyType extends CommonListType {
        public CompanyType() {
        }
        public CompanyType(int id, String name) {
            super(id, name);
        }
    }

    public static class CompanySize extends CommonListType {
        public CompanySize() {
        }
        public CompanySize(int id, String name) {
            super(id, name);
        }
    }

    public static class Province extends CommonListType {
    	private List<City> cities = new ArrayList<City>();
        public Province() {
        }
        public Province(int id, String name) {
            super(id, name);
        }
        public List<City> getCities() {
        	return cities;
        }
        public void addCity(City city) {
        	cities.add(city);
        }
    }

    public static class City extends CommonListType {
        public City() {
        }
        public City(int id, String name) {
            super(id, name);
            int provinceId = id / 10000;
            for (Province province : Constants.PROVINCES) {
            	if (province.getId() == provinceId) {
            		province.addCity(this);
            		break;
            	}
            }
        }
    }

    public static class Language extends CommonListType {
        public Language() {
        }
        public Language(int id, String name) {
            super(id, name);
        }
    }

    public static class Proficiency extends CommonListType {
        public Proficiency() {
        }
        public Proficiency(int id, String name) {
            super(id, name);
        }
    }

    public static class Education extends CommonListType {
        public Education() {
        }
        public Education(int id, String name) {
            super(id, name);
        }
    }

    public static class WorkingYear extends CommonListType {
        public WorkingYear() {
        }
        public WorkingYear(int id, String name) {
            super(id, name);
        }
    }

    public static class SalaryRange extends CommonListType {
        public SalaryRange() {
        }
        public SalaryRange(int id, String name) {
            super(id, name);
        }
    }

    public static class JobType extends CommonListType {
        public JobType() {
        }
        public JobType(int id, String name) {
            super(id, name);
        }
    }

    public static class Major extends CommonListType {
        public Major() {
        }
        public Major(int id, String name) {
            super(id, name);
        }
    }

    public static class CertType extends CommonListType {
        public CertType() {
        }
        public CertType(int id, String name) {
            super(id, name);
        }
    }

    public static class Currency extends CommonListType {
        public Currency() {
        }
        public Currency(int id, String name) {
            super(id, name);
        }
    }

    public static class Situation extends CommonListType {
        public Situation() {
        }
        public Situation(int id, String name) {
            super(id, name);
        }
    }

    public static class Country extends CommonListType {
        public Country() {
        }
        public Country(int id, String name) {
            super(id, name);
        }
    }

    public static class MarriageStatus extends CommonListType {
        public MarriageStatus() {
        }
        public MarriageStatus(int id, String name) {
            super(id, name);
        }
    }

    public static class PoliticalStatus extends CommonListType {
        public PoliticalStatus() {
        }
        public PoliticalStatus(int id, String name) {
            super(id, name);
        }
    }

    public static String getProvinceJson() {
        return PROVINCES_JSON;
    }

    public static String getCityJson() {
        return CITIES_JSON;
    }

    public static final List<CompanyType> COMPANY_TYPES = new ArrayList<CompanyType>();
    public static final List<CompanySize> COMPANY_SIZES = new ArrayList<CompanySize>();
    public static final List<Province> PROVINCES = new ArrayList<Province>();
    public static final List<City> CITIES = new ArrayList<City>();
    private static String PROVINCES_JSON;
    private static String CITIES_JSON;
    public static final List<Language> LANGUAGES = new ArrayList<Language>();
    public static final List<Proficiency> PROFICIENCYS = new ArrayList<Proficiency>();
    public static final List<Education> EDUCATIONS = new ArrayList<Education>();
    public static final List<WorkingYear> WORKING_YEARS = new ArrayList<WorkingYear>();
    public static final List<WorkingYear> WORKING_YEARS_MEMBER = new ArrayList<WorkingYear>();
    public static final List<SalaryRange> SALARY_RANGES = new ArrayList<SalaryRange>();
    public static final List<JobType> JOB_TYPES = new ArrayList<JobType>();
    public static final List<Major> MAJORS = new ArrayList<Major>();
    public static final List<CertType> CERT_TYPES = new ArrayList<CertType>();
    public static final List<SalaryRange> YEARLY_SALARY_RANGES = new ArrayList<SalaryRange>();
    public static final List<Currency> CURRENCIES = new ArrayList<Currency>();
    public static final List<Situation> SITUATIONS = new ArrayList<Situation>();
    public static final List<Country> COUNTRIES = new ArrayList<Country>();
    public static final List<MarriageStatus> MARRIAGE_STATUS = new ArrayList<MarriageStatus>();
    public static final List<PoliticalStatus> POLITICAL_STATUS = new ArrayList<PoliticalStatus>();

    @SuppressWarnings("rawtypes")
    private static class ConstantDef {
        @SuppressWarnings("unused")
        public String name;
        public List obj;
        public Class cls;
        public Constructor constructor;

        @SuppressWarnings("unchecked")
        public ConstantDef(String name, List obj, Class cls) throws Exception {
            this.name = name;
            this.obj = obj;
            this.cls = cls;
            this.constructor = this.cls.getConstructor(int.class, String.class);
        }
    }

    private static Map<String, ConstantDef> registeredConstants = new HashMap<String, ConstantDef>();

    @SuppressWarnings({ "unchecked" })
    static void init() {
        try {
            registeredConstants.put("[CompanyType]", new ConstantDef("CompanyType", COMPANY_TYPES, CompanyType.class));
            registeredConstants.put("[CompanySize]", new ConstantDef("CompanySize", COMPANY_SIZES, CompanySize.class));
            registeredConstants.put("[Province]", new ConstantDef("Province", PROVINCES, Province.class));
            registeredConstants.put("[City]", new ConstantDef("City", CITIES, City.class));
            registeredConstants.put("[Language]", new ConstantDef("Language", LANGUAGES, Language.class));
            registeredConstants.put("[Proficiency]", new ConstantDef("Proficiency", PROFICIENCYS, Proficiency.class));
            registeredConstants.put("[Education]", new ConstantDef("Education", EDUCATIONS, Education.class));
            registeredConstants.put("[WorkingYearMember]", new ConstantDef("WorkingYearMember", WORKING_YEARS_MEMBER, WorkingYear.class));
            registeredConstants.put("[WorkingYear]", new ConstantDef("WorkingYear", WORKING_YEARS, WorkingYear.class));
            registeredConstants.put("[SalaryRange]", new ConstantDef("SalaryRange", SALARY_RANGES, SalaryRange.class));
            registeredConstants.put("[JobType]", new ConstantDef("JobType", JOB_TYPES, JobType.class));
            registeredConstants.put("[Major]", new ConstantDef("Major", MAJORS, Major.class));
            registeredConstants.put("[CertType]", new ConstantDef("CertType", CERT_TYPES, CertType.class));
            registeredConstants.put("[YearlySalaryRange]", new ConstantDef("YearlySalaryRange", YEARLY_SALARY_RANGES,
                    SalaryRange.class));
            registeredConstants.put("[Currency]", new ConstantDef("Currency", CURRENCIES, Currency.class));
            registeredConstants.put("[Situation]", new ConstantDef("Situation", SITUATIONS, Situation.class));
            registeredConstants.put("[Country]", new ConstantDef("Country", COUNTRIES, Country.class));
            registeredConstants.put("[MarriageStatus]", new ConstantDef("MarriageStatus", MARRIAGE_STATUS,
                    MarriageStatus.class));
            registeredConstants.put("[PoliticalStatus]", new ConstantDef("PoliticalStatus", POLITICAL_STATUS,
                    PoliticalStatus.class));

            InputStream is = Constants.class.getResourceAsStream("constants.txt");
            BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            ConstantDef def = null;
            String line;
            while ((line = br.readLine()) != null) {
                if ((line = line.trim()).isEmpty()) {
                    continue;
                }
                if (line.startsWith("[")) {
                    def = registeredConstants.get(line);
                } else {
                    int index = line.indexOf(":");
                    int id = Integer.parseInt(line.substring(0, index));
                    String name = line.substring(index + 1);
                    def.obj.add(def.constructor.newInstance(id, name));
                }
            }
            br.close();
            ObjectMapper mapper = new ObjectMapper();
            PROVINCES_JSON = mapper.writeValueAsString(PROVINCES);
            CITIES_JSON = mapper.writeValueAsString(CITIES);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static {
        init();
    }
}
